package org.hoyi.microservice.configers.nginx;

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;

import org.hoyi.microservice.HoyiCloudApplication;
import org.hoyi.microservice.HoyiServiceManagement;
import org.hoyi.microservice.routes.model.HoyiProvider;
import org.hoyi.microservice.routes.model.HoyiRouteRule;
import org.hoyi.microservice.routes.model.HoyiRouter;

public class nginxConfExe {

	private static nginxConfExe _instance;

	public static nginxConfExe getInstance() {
		if (_instance == null) {
			_instance = new nginxConfExe();
		}
		return _instance;
	}
	
	/**
	 * 发布路由，当服务注册、添加路由的时候，可以主动发布路由.
	 */
	public void PublishRoute() {
		String nginxconfig = nginxConfExe.getInstance().BuildConfig();
		// 保存到文件。
		String configpath = HoyiCloudApplication.hoyiconfig.getNGINX().get("CONF-URL");// "/usr/local/etc/nginx/hoyi-cloud-nginx.conf";
		
		nginxConfExe.getInstance().SaveConfig(nginxconfig, configpath);
		
		String baturl = HoyiCloudApplication.hoyiconfig.getNGINX().get("SHELL-URL");
		nginxConfExe.getInstance().runbat(baturl);;
	}
	
	/**
	 * 有效.
	 * @param baturl
	 */
	public void runbat(String baturl) {
		String cmd = "cmd /C start /b " + baturl;// pass
		try {
			Process ps = Runtime.getRuntime().exec(cmd);
			InputStream in = ps.getInputStream();
//			int c;
//			while ((c = in.read()) != -1) {
//				System.out.print(c);// 如果你不需要看输出，这行可以注销掉
//			}
			in.close();
//			ps.waitFor();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		} 
		System.out.println("child thread donn");
	}

	/**
	 * 执行有效.
	 * 
	 * 
	// 可行
//	String command1="cmd /c cd D:/Soft/ServerTools/nginx/nginx-1.11.10";
//    String command2="cmd /c D:";
//    String command3="cmd /c nginx.exe -s reload";
//	nginxConfExe.getInstance().runShell(command1 + " && " + command2 + " && " + command3, "WINDOWS");
	 * 
	 * @param shStr
	 * @param ostype
	 * @return value
	 * @throws Exception
	 */
	public static String runShell(String shStr, String ostype) throws Exception {

		Process process;
		if (ostype.toUpperCase().equals("WINDOWS")) {
			process = Runtime.getRuntime().exec(new String[] { "cmd", "-c", shStr });
		} else {
			process = Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", shStr });
		}
		process.waitFor();
		BufferedReader read = new BufferedReader(new InputStreamReader(process.getInputStream()));
		String line = null;
		String result = "";
		while ((line = read.readLine()) != null) {
			result += line;
		}
		return result;
	}

	/**
	 * 无效。
	 * 
	 * @param cmd
	 * @return value
	 */
	public static Object exec(String cmd) {
		try {
			String[] cmdA = { "/bin/sh", "-c", cmd };
			Process process = Runtime.getRuntime().exec(cmdA);
			LineNumberReader br = new LineNumberReader(new InputStreamReader(process.getInputStream()));
			StringBuffer sb = new StringBuffer();
			String line;
			while ((line = br.readLine()) != null) {
				System.out.println(line);
				sb.append(line).append("\n");
			}
			return sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 讲配置文件保存。
	 * @param configcontent
	 * @param path
	 */
	public void SaveConfig(String configcontent, String path) {
		FileWriter fwriter = null;
		try {
			fwriter = new FileWriter(path);
			fwriter.write(configcontent);
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			try {
				fwriter.flush();
				fwriter.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}

	public void AL(StringBuilder stringBuilder, String content) {
		stringBuilder.append(content + "\n");

		// stringBuilder.append(content + "\"+'\\n'+\"");
	}

	public void AX(StringBuilder stringBuilder, String content) {
		stringBuilder.append(content + "\n\n");

		// stringBuilder.append(content + "\"+'\\n'+\"" + "\"+'\\n'+\"");
	}

	public String BuildAlertConfig() {
		String config = BuildConfig();
		config = config.replaceAll("\n", "\\\"+'\\\\n'+\\\"");
		return config;
	}

	public String BuildConfig() {
		StringBuilder sb = new StringBuilder();

		StringBuilder upstream = new StringBuilder();
		List<StringBuilder> upstreambuilders = new ArrayList<>();
		// 已经生成的ID记录。
		List<String> upstridexed = new ArrayList<>();

		AL(sb, "#user root owner;");
		AL(sb, "worker_processes  1;");
		AL(sb, "   ");

		AL(sb, "#error_log  logs/error.log;");
		AL(sb, "#error_log  logs/error.log notice;");
		AX(sb, "#error_log  logs/error.log; info");

		AL(sb, "events {");
		AL(sb, "    worker_connections  1024;");
		AX(sb, "}");

		AX(sb, "http {");

		AL(sb, "	include       mime.types;");
		AX(sb, "	default_type  application/octet-stream;");

		AL(sb, "	sendfile        on;");
		AL(sb, "	#tcp_nopush     on;");
		AL(sb, "	#keepalive_timeout  0;");
		AX(sb, "	keepalive_timeout  65;");

		AL(sb, "   	#gzip  on;");

		for (HoyiRouter router : HoyiServiceManagement.getInstance().getRouters()) {
			AL(sb, "	server {");

			AL(sb, "			listen       " + router.getPort() + ";");
			AX(sb, "			server_name  " + router.getHost() + ";");

			for (HoyiRouteRule rules : router.getRules()) {
				AL(sb, "			location " + rules.getLocation() + " {");
				if (rules.getLOCALURL() != null && rules.getLOCALURL().trim().length() > 0) {
					AL(sb, "				" + rules.getLOCALURL() + ";");
				}
				if (rules.getProxyPass() != null && rules.getProxyPass().trim().length() > 0) {
					AL(sb, "				proxy_pass   " + rules.getProxyPass() + ";");
					AL(sb, "				proxy_set_header Host $host;");
				}
				upstream = new StringBuilder();
				if (rules.getProviderids() != null && rules.getProviderids().trim().length() > 0) {
					List<HoyiProvider> streamproviders = HoyiServiceManagement.getInstance()
							.GetProvider(rules.getProviderids());
					String curserviceid = streamproviders.get(0).getServiceID();
					AL(sb, "				proxy_pass   http://" + curserviceid + "/;");
					if (streamproviders.size() > 0) {
						if (!upstridexed.contains(curserviceid)) {
							if (streamproviders.size() > 0) {
								AL(upstream, "	upstream " + curserviceid + "{");
							}
							for (HoyiProvider _provider : streamproviders) {
								AL(upstream, "		server " + _provider.getHost() + ":" + _provider.getPort()
										+ " weight=1;");
							}
							if (streamproviders.size() > 0) {
								AX(upstream, "	}");
							}
							upstridexed.add(curserviceid);
						}
					}
				}
				upstreambuilders.add(upstream);
				AX(sb, "			}");
			}

			AX(sb, "	}");
		}

		for (StringBuilder _stringBuilder : upstreambuilders) {
			sb.append(_stringBuilder.toString());
		}

		AL(sb, "}");

		return sb.toString();
	}

}
